package com.leenmvc.core.utils.collection;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.*;
import java.util.Map.Entry;

public class MapUtils {
    private static final String INDENT_STRING = "    ";

    public MapUtils() {
    }

    public static Object getObject(Map map, Object key) {
        return map != null ? map.get(key) : null;
    }

    public static String getString(Map map, Object key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                return answer.toString();
            }
        }

        return null;
    }

    public static Boolean getBoolean(Map map, Object key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                if (answer instanceof Boolean) {
                    return (Boolean) answer;
                }

                if (answer instanceof String) {
                    return new Boolean((String) answer);
                }

                if (answer instanceof Number) {
                    Number n = (Number) answer;
                    return n.intValue() != 0 ? Boolean.TRUE : Boolean.FALSE;
                }
            }
        }
        return null;
    }

    public static Number getNumber(Map map, Object key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                if (answer instanceof Number) {
                    return (Number) answer;
                }

                if (answer instanceof String) {
                    try {
                        String text = (String) answer;
                        return NumberFormat.getInstance().parse(text);
                    } catch (ParseException var4) {

                    }
                }
            }
        }

        return null;
    }

    public static Byte getByte(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Byte ? (Byte) answer : new Byte(answer.byteValue());
        }
    }

    public static Short getShort(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Short ? (Short) answer : new Short(answer.shortValue());
        }
    }

    public static Integer getInteger(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Integer ? (Integer) answer : new Integer(answer.intValue());
        }
    }

    public static Long getLong(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Long ? (Long) answer : new Long(answer.longValue());
        }
    }

    public static Float getFloat(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Float ? (Float) answer : new Float(answer.floatValue());
        }
    }

    public static Double getDouble(Map map, Object key) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            return null;
        } else {
            return answer instanceof Double ? (Double) answer : new Double(answer.doubleValue());
        }
    }

    public static Map getMap(Map map, Object key) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null && answer instanceof Map) {
                return (Map) answer;
            }
        }

        return null;
    }

    public static Object getObject(Map map, Object key, Object defaultValue) {
        if (map != null) {
            Object answer = map.get(key);
            if (answer != null) {
                return answer;
            }
        }

        return defaultValue;
    }

    public static String getString(Map map, Object key, String defaultValue) {
        String answer = getString(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Boolean getBoolean(Map map, Object key, Boolean defaultValue) {
        Boolean answer = getBoolean(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Number getNumber(Map map, Object key, Number defaultValue) {
        Number answer = getNumber(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Byte getByte(Map map, Object key, Byte defaultValue) {
        Byte answer = getByte(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Short getShort(Map map, Object key, Short defaultValue) {
        Short answer = getShort(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Integer getInteger(Map map, Object key, Integer defaultValue) {
        Integer answer = getInteger(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Long getLong(Map map, Object key, Long defaultValue) {
        Long answer = getLong(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Float getFloat(Map map, Object key, Float defaultValue) {
        Float answer = getFloat(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Double getDouble(Map map, Object key, Double defaultValue) {
        Double answer = getDouble(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static Map getMap(Map map, Object key, Map defaultValue) {
        Map answer = getMap(map, key);
        if (answer == null) {
            answer = defaultValue;
        }

        return answer;
    }

    public static boolean getBooleanValue(Map map, Object key) {
        Boolean booleanObject = getBoolean(map, key);
        return booleanObject == null ? false : booleanObject;
    }

    public static byte getByteValue(Map map, Object key) {
        Byte byteObject = getByte(map, key);
        return byteObject == null ? 0 : byteObject;
    }

    public static short getShortValue(Map map, Object key) {
        Short shortObject = getShort(map, key);
        return shortObject == null ? 0 : shortObject;
    }

    public static int getIntValue(Map map, Object key) {
        Integer integerObject = getInteger(map, key);
        return integerObject == null ? 0 : integerObject;
    }

    public static long getLongValue(Map map, Object key) {
        Long longObject = getLong(map, key);
        return longObject == null ? 0L : longObject;
    }

    public static float getFloatValue(Map map, Object key) {
        Float floatObject = getFloat(map, key);
        return floatObject == null ? 0.0F : floatObject;
    }

    public static double getDoubleValue(Map map, Object key) {
        Double doubleObject = getDouble(map, key);
        return doubleObject == null ? 0.0D : doubleObject;
    }

    public static boolean getBooleanValue(Map map, Object key, boolean defaultValue) {
        Boolean booleanObject = getBoolean(map, key);
        return booleanObject == null ? defaultValue : booleanObject;
    }

    public static byte getByteValue(Map map, Object key, byte defaultValue) {
        Byte byteObject = getByte(map, key);
        return byteObject == null ? defaultValue : byteObject;
    }

    public static short getShortValue(Map map, Object key, short defaultValue) {
        Short shortObject = getShort(map, key);
        return shortObject == null ? defaultValue : shortObject;
    }

    public static int getIntValue(Map map, Object key, int defaultValue) {
        Integer integerObject = getInteger(map, key);
        return integerObject == null ? defaultValue : integerObject;
    }

    public static long getLongValue(Map map, Object key, long defaultValue) {
        Long longObject = getLong(map, key);
        return longObject == null ? defaultValue : longObject;
    }

    public static float getFloatValue(Map map, Object key, float defaultValue) {
        Float floatObject = getFloat(map, key);
        return floatObject == null ? defaultValue : floatObject;
    }

    public static double getDoubleValue(Map map, Object key, double defaultValue) {
        Double doubleObject = getDouble(map, key);
        return doubleObject == null ? defaultValue : doubleObject;
    }

    public static Properties toProperties(Map map) {
        Properties answer = new Properties();
        if (map != null) {
            Iterator iter = map.entrySet().iterator();

            while (iter.hasNext()) {
                Entry entry = (Entry) iter.next();
                Object key = entry.getKey();
                Object value = entry.getValue();
                answer.put(key, value);
            }
        }

        return answer;
    }

    public static Map toMap(ResourceBundle resourceBundle) {
        Enumeration enumeration = resourceBundle.getKeys();
        HashMap map = new HashMap();

        while (enumeration.hasMoreElements()) {
            String key = (String) enumeration.nextElement();
            Object value = resourceBundle.getObject(key);
            map.put(key, value);
        }

        return map;
    }

    public static boolean isEmpty(Map map) {
        return map == null || map.isEmpty();
    }

    public static boolean isNotEmpty(Map map) {
        return !isEmpty(map);
    }

    public static Map synchronizedMap(Map map) {
        return Collections.synchronizedMap(map);
    }


    /**
     * 清空为null值的键值对
     *
     * @param map
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> clearNullKV(Map<K, V> map) {
        Map<K, V> result = new HashMap<>();
        for (K k : map.keySet()) {
            if (map.get(k) != null) {
                result.put(k, map.get(k));
            }
        }
        return result;
    }

    /**
     * @param map
     * @param <T>
     * @param <V>
     * @return
     */
    public static <T, V> Map<T, V> hashmapTolinkHashMap(Map<T, V> map) {
        Map<T, V> linkedHashMap = new LinkedHashMap<>();
        List<T> list = new ArrayList<>();
        Iterator<T> item = map.keySet().iterator();
        while (item.hasNext()) {
            list.add(item.next());
        }
        Iterator<T> item2 = list.iterator();
        while (item2.hasNext()) {
            T key = item2.next();
            linkedHashMap.put(key, map.get(key));
        }
        return linkedHashMap;
    }

    /**
     * entity转换map
     *
     * @param entity
     * @return
     */
    public static Map<String, Object> entityToMap(Object entity) {
        Map<String, Object> result = new HashMap<>();
        if (entity == null) {
            return null;
        }
        Class<?> entityClass = entity.getClass();
        Field[] fields = entityClass.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                result.put(field.getName(), field.get(entity));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * map集合转换成实体类
     *
     * @param map
     * @param target
     * @return
     */
    public static <T> T mapToEntity(Map<String, Object> map, Class<T> target) {
        if (map == null) {
            return null;
        }
        T t = null;
        try {
            t = target.newInstance();
            Field[] fields = t.getClass().getDeclaredFields();
            for (Field field : fields) {
                int modifiers = field.getModifiers();
                if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
                    continue;
                }
                field.setAccessible(true);
                field.set(t, map.get(field.getName()));
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 将数组转成hashmap
     *
     * @param KVs
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K,V> arrayToMap(Object[] KVs) {
        Map<String, Object> params = new HashMap<>();
        for(int i = 0 ; i < KVs.length; i+=2) {
            params.put(String.valueOf(KVs[i]), KVs[i+1]);
        }
        return (Map<K,V>)params;
    }

}
